package io.terminus.lego.shinda.web.security.service

import com.fasterxml.jackson.annotation.JsonInclude
import com.fasterxml.jackson.core.JsonGenerator
import com.fasterxml.jackson.databind.DeserializationFeature
import com.fasterxml.jackson.databind.ObjectMapper
import io.terminus.lego.shinda.service.model.toMap
import io.terminus.lego.shinda.service.service.UserService
import io.terminus.lego.shinda.web.context.BindingContext
import io.terminus.lego.shinda.web.security.enums.OAuth2UserConvertKeyEnum
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService
import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest
import org.springframework.security.oauth2.core.user.DefaultOAuth2User
import org.springframework.security.oauth2.core.user.OAuth2User
import org.springframework.stereotype.Component
import javax.annotation.PostConstruct

/**
 * 通过OAuth2登录的用户，要转换成用户中心的用户
 * @author wangmeng
 * @date 2018/4/16
 */
@Component
class UCOAuth2UserService @Autowired constructor(val userService: UserService) : DefaultOAuth2UserService() {

    val objectMapper = ObjectMapper()

    @PostConstruct
    fun init() {
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL)
        objectMapper.configure(JsonGenerator.Feature.IGNORE_UNKNOWN, true)
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
    }

    private fun toJson(target: Any): String {
        return objectMapper.writeValueAsString(target)
    }

    override fun loadUser(userRequest: OAuth2UserRequest): OAuth2User {
        val oAuth2User = super.loadUser(userRequest)
        val registration = userRequest.clientRegistration

        val providerId = registration.registrationId
        val providerUserId = oAuth2User.name

        var user = userService.findByProviderIdAndPorviderUserId(providerId, providerUserId)
        println("----------> " + BindingContext.username.get())
        println("----------> " + BindingContext.target.get())
        if (user == null) {
            //获取provider对应的转换辅助枚举
            val convertKey = OAuth2UserConvertKeyEnum.getByProviderId(providerId)
            if (!BindingContext.username.get().isNullOrEmpty()) {
                //绑定信息存在、则查找对应的用户，增加映射关系
                user = userService.findUserById(BindingContext.username.get().toLong())!!
                userService.createRelation(user.id!!, providerId, providerUserId,
                        oAuth2User.attributes[convertKey.nickNameKey].toString(),
                        oAuth2User.attributes [convertKey.avatarUrlKey].toString(),
                        toJson(oAuth2User.attributes))
            } else {
                //绑定信息不存在、则新增用户
                user = userService.createByProviderUser(providerId, providerUserId,
                        oAuth2User.attributes[convertKey.nickNameKey].toString(),
                        oAuth2User.attributes [convertKey.avatarUrlKey].toString(),
                        toJson(oAuth2User.attributes))

            }
        }
        BindingContext.username.remove()
        BindingContext.target.remove()
        //返回的是认证后的用户详情,username将成为为authentication.name
        return DefaultOAuth2User(oAuth2User.authorities.toSet(), user.toMap(), "username")
    }
}